<html>
<head><meta charset="utf-8"><title>conditional-control-flow-across-functions-and-iterators · t-compiler/wg-nll · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/122657-t-compiler/wg-nll/index.html">t-compiler/wg-nll</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/122657-t-compiler/wg-nll/topic/conditional-control-flow-across-functions-and-iterators.html">conditional-control-flow-across-functions-and-iterators</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="128495964"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122657-t-compiler/wg-nll/topic/conditional-control-flow-across-functions-and-iterators/near/128495964" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122657-t-compiler/wg-nll/topic/conditional-control-flow-across-functions-and-iterators.html#128495964">(Jun 22 2018 at 22:01)</a>:</h4>
<p>I found a case where the boring, non-iterator based code works with NLL+Polonius, but the idiomatic iterator version does not:</p>
<div class="codehilite"><pre><span></span><span class="c1">// rustc 1.28.0-nightly (ae46aefd5 2018-06-16)</span>
<span class="c1">// cargo +nightly rustc -- -Z polonius</span>
<span class="cp">#![feature(nll)]</span><span class="w"></span>

<span class="k">struct</span> <span class="nc">Reader</span><span class="p">;</span><span class="w"></span>
<span class="k">struct</span> <span class="nc">Data</span><span class="p">;</span><span class="w"></span>
<span class="k">struct</span> <span class="nc">Errors</span><span class="o">&lt;</span><span class="na">&#39;a</span><span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="na">&#39;a</span><span class="w"> </span><span class="kt">str</span><span class="p">);</span><span class="w"></span>

<span class="k">fn</span> <span class="nf">handle_array</span><span class="p">(</span><span class="n">stream</span>: <span class="kp">&amp;</span><span class="nc">mut</span><span class="w"> </span><span class="n">Reader</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nb">Result</span><span class="o">&lt;</span><span class="n">Data</span><span class="p">,</span><span class="w"> </span><span class="n">Errors</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="c1">// Works</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">array</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">vec</span><span class="o">!</span><span class="p">[];</span><span class="w"></span>
<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="n">_</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="p">(</span><span class="mi">0</span><span class="p">..</span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="n">array</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="n">handle_request</span><span class="p">(</span><span class="n">stream</span><span class="p">)</span><span class="o">?</span><span class="p">);</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>

<span class="w">    </span><span class="c1">// Does not work</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">array</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="mi">0</span><span class="p">..</span><span class="mi">0</span><span class="p">)</span><span class="w"></span>
<span class="w">        </span><span class="p">.</span><span class="n">map</span><span class="p">(</span><span class="o">|</span><span class="n">_</span><span class="o">|</span><span class="w"> </span><span class="n">handle_request</span><span class="p">(</span><span class="n">stream</span><span class="p">))</span><span class="w"></span>
<span class="w">        </span><span class="p">.</span><span class="n">collect</span>::<span class="o">&lt;</span><span class="nb">Result</span><span class="o">&lt;</span><span class="nb">Vec</span><span class="o">&lt;</span><span class="n">_</span><span class="o">&gt;</span><span class="p">,</span><span class="w"> </span><span class="n">_</span><span class="o">&gt;&gt;</span><span class="p">()</span><span class="o">?</span><span class="p">;</span><span class="w"></span>

<span class="w">    </span><span class="n">unimplemented</span><span class="o">!</span><span class="p">();</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="k">fn</span> <span class="nf">handle_request</span><span class="p">(</span><span class="n">_stream</span>: <span class="kp">&amp;</span><span class="nc">mut</span><span class="w"> </span><span class="n">Reader</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nb">Result</span><span class="o">&lt;</span><span class="n">Data</span><span class="p">,</span><span class="w"> </span><span class="n">Errors</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="n">unimplemented</span><span class="o">!</span><span class="p">()</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{}</span><span class="w"></span>
</pre></div>


<p>Is this worth an issue?</p>



<a name="128496268"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122657-t-compiler/wg-nll/topic/conditional-control-flow-across-functions-and-iterators/near/128496268" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> lqd <a href="https://rust-lang.github.io/zulip_archive/stream/122657-t-compiler/wg-nll/topic/conditional-control-flow-across-functions-and-iterators.html#128496268">(Jun 22 2018 at 22:09)</a>:</h4>
<p>I would think so :)</p>



<a name="128496274"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122657-t-compiler/wg-nll/topic/conditional-control-flow-across-functions-and-iterators/near/128496274" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122657-t-compiler/wg-nll/topic/conditional-control-flow-across-functions-and-iterators.html#128496274">(Jun 22 2018 at 22:09)</a>:</h4>
<p>Oh, I guess that can't be safe. Since it could be collected into a <code>Vec&lt;Errors&gt;</code> which would then allow for mutable aliasing, yeah?</p>



<a name="128599866"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122657-t-compiler/wg-nll/topic/conditional-control-flow-across-functions-and-iterators/near/128599866" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Vytautas Astrauskas [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/122657-t-compiler/wg-nll/topic/conditional-control-flow-across-functions-and-iterators.html#128599866">(Jun 25 2018 at 13:27)</a>:</h4>
<p><span class="user-mention" data-user-id="116155">@Jake Goulding</span> For your example, the compiler reports what I would expect it to report. The type of the first array is <code>Vec&lt;Data&gt;</code> – therefore, we know that it does not capture the <code>stream</code>. However, the type of the second array is <code>Vec&lt;Result&lt;Data, Errors&lt;'a&gt;&gt;&gt;</code>, which may capture the<code>stream</code>. I guess that if you managed to write something similar to <code>map(|_| handle_request(stream)?)</code>, then also the second version would compile.</p>



<a name="128599966"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122657-t-compiler/wg-nll/topic/conditional-control-flow-across-functions-and-iterators/near/128599966" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122657-t-compiler/wg-nll/topic/conditional-control-flow-across-functions-and-iterators.html#128599966">(Jun 25 2018 at 13:29)</a>:</h4>
<p>that sounds like it agrees with my followup comment; do you concur?</p>



<a name="128600593"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122657-t-compiler/wg-nll/topic/conditional-control-flow-across-functions-and-iterators/near/128600593" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Vytautas Astrauskas [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/122657-t-compiler/wg-nll/topic/conditional-control-flow-across-functions-and-iterators.html#128600593">(Jun 25 2018 at 13:43)</a>:</h4>
<p>I mostly agree with your follow up comment. To me, it seems that both versions are actually safe because <code>Errors</code> take a shared reference. However, since the compiler does the modular analysis, it does not see that and to be on the safe side reports an error. In other words: the compiler thinks that there could be mutable aliasing and, therefore, rejects the code.</p>



<a name="128600856"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122657-t-compiler/wg-nll/topic/conditional-control-flow-across-functions-and-iterators/near/128600856" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122657-t-compiler/wg-nll/topic/conditional-control-flow-across-functions-and-iterators.html#128600856">(Jun 25 2018 at 13:49)</a>:</h4>
<blockquote>
<p><code>Errors</code> take a shared reference.</p>
</blockquote>
<p>Well, but even if that's the case, something would be holding the immutable reference while the loop continues on trying to use the mutable reference. </p>
<p>I agree it ultimately seems safe, but that's only because we "know" that the implementation of <code>&lt;Vec as FromIterator&gt;</code> / <code>Vec::push</code> doesn't look at the references it holds as it goes on to the next element</p>



<a name="128609884"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122657-t-compiler/wg-nll/topic/conditional-control-flow-across-functions-and-iterators/near/128609884" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Vytautas Astrauskas [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/122657-t-compiler/wg-nll/topic/conditional-control-flow-across-functions-and-iterators.html#128609884">(Jun 25 2018 at 16:44)</a>:</h4>
<p>Yes, you are completely right. I forgot about the iterator.</p>



<a name="128618986"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122657-t-compiler/wg-nll/topic/conditional-control-flow-across-functions-and-iterators/near/128618986" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nikomatsakis <a href="https://rust-lang.github.io/zulip_archive/stream/122657-t-compiler/wg-nll/topic/conditional-control-flow-across-functions-and-iterators.html#128618986">(Jun 25 2018 at 19:45)</a>:</h4>
<p><span class="user-mention" data-user-id="116155">@Jake Goulding</span> a nit. I would've found this <strong>so much</strong> easier to read if you would use <code>'_</code>:</p>
<div class="codehilite"><pre><span></span><span class="k">fn</span> <span class="nf">handle_request</span><span class="p">(</span><span class="n">_stream</span>: <span class="kp">&amp;</span><span class="nc">mut</span><span class="w"> </span><span class="n">Reader</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nb">Result</span><span class="o">&lt;</span><span class="n">Data</span><span class="p">,</span><span class="w"> </span><span class="n">Errors</span><span class="o">&lt;</span><span class="na">&#39;_</span><span class="o">&gt;&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="n">unimplemented</span><span class="o">!</span><span class="p">()</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</pre></div>


<p>As is, I spent a long time being puzzled because I didn't realize that <code>Errors</code> carried a lifetime</p>



<a name="128619070"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122657-t-compiler/wg-nll/topic/conditional-control-flow-across-functions-and-iterators/near/128619070" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122657-t-compiler/wg-nll/topic/conditional-control-flow-across-functions-and-iterators.html#128619070">(Jun 25 2018 at 19:46)</a>:</h4>
<blockquote>
<p><span class="user-mention" data-user-id="116155">@Jake Goulding</span> a nit. I would've found this <strong>so much</strong> easier to read if you would use <code>'_</code>:</p>
</blockquote>
<p>Hey, make it stable and I'll start getting used to it ;-)</p>



<a name="128619087"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122657-t-compiler/wg-nll/topic/conditional-control-flow-across-functions-and-iterators/near/128619087" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nikomatsakis <a href="https://rust-lang.github.io/zulip_archive/stream/122657-t-compiler/wg-nll/topic/conditional-control-flow-across-functions-and-iterators.html#128619087">(Jun 25 2018 at 19:47)</a>:</h4>
<p>I think it is</p>



<a name="128619093"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122657-t-compiler/wg-nll/topic/conditional-control-flow-across-functions-and-iterators/near/128619093" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nikomatsakis <a href="https://rust-lang.github.io/zulip_archive/stream/122657-t-compiler/wg-nll/topic/conditional-control-flow-across-functions-and-iterators.html#128619093">(Jun 25 2018 at 19:47)</a>:</h4>
<p>but maybe not?</p>



<a name="128619096"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122657-t-compiler/wg-nll/topic/conditional-control-flow-across-functions-and-iterators/near/128619096" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nikomatsakis <a href="https://rust-lang.github.io/zulip_archive/stream/122657-t-compiler/wg-nll/topic/conditional-control-flow-across-functions-and-iterators.html#128619096">(Jun 25 2018 at 19:47)</a>:</h4>
<p>that said, the lint that encourages you to migrate I think still needs work</p>



<a name="128619177"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122657-t-compiler/wg-nll/topic/conditional-control-flow-across-functions-and-iterators/near/128619177" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122657-t-compiler/wg-nll/topic/conditional-control-flow-across-functions-and-iterators.html#128619177">(Jun 25 2018 at 19:49)</a>:</h4>
<blockquote>
<p>I think it is</p>
</blockquote>
<p>Well, I'll be.</p>
<div class="codehilite"><pre><span></span><span class="k">struct</span> <span class="nc">A</span><span class="o">&lt;</span><span class="na">&#39;a</span><span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="na">&#39;a</span><span class="w"> </span><span class="p">());</span><span class="w"></span>

<span class="k">struct</span> <span class="nc">X</span><span class="p">;</span><span class="w"></span>
<span class="k">impl</span><span class="w"> </span><span class="n">X</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="k">fn</span> <span class="nf">x</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nc">A</span><span class="o">&lt;</span><span class="na">&#39;_</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="n">unimplemented</span><span class="o">!</span><span class="p">()</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{}</span><span class="w"></span>
</pre></div>



<a name="128619186"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122657-t-compiler/wg-nll/topic/conditional-control-flow-across-functions-and-iterators/near/128619186" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122657-t-compiler/wg-nll/topic/conditional-control-flow-across-functions-and-iterators.html#128619186">(Jun 25 2018 at 19:49)</a>:</h4>
<p>And yeah, there doesn't <em>seem</em> to be a lint...</p>



<a name="128619191"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122657-t-compiler/wg-nll/topic/conditional-control-flow-across-functions-and-iterators/near/128619191" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122657-t-compiler/wg-nll/topic/conditional-control-flow-across-functions-and-iterators.html#128619191">(Jun 25 2018 at 19:49)</a>:</h4>
<p>But yeah, that's cool it's stable. Wonder when that happened.</p>



<a name="128619255"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122657-t-compiler/wg-nll/topic/conditional-control-flow-across-functions-and-iterators/near/128619255" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nikomatsakis <a href="https://rust-lang.github.io/zulip_archive/stream/122657-t-compiler/wg-nll/topic/conditional-control-flow-across-functions-and-iterators.html#128619255">(Jun 25 2018 at 19:50)</a>:</h4>
<p>there is a lint</p>



<a name="128619258"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122657-t-compiler/wg-nll/topic/conditional-control-flow-across-functions-and-iterators/near/128619258" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nikomatsakis <a href="https://rust-lang.github.io/zulip_archive/stream/122657-t-compiler/wg-nll/topic/conditional-control-flow-across-functions-and-iterators.html#128619258">(Jun 25 2018 at 19:50)</a>:</h4>
<p>it's just not enabled by default</p>



<a name="128619294"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122657-t-compiler/wg-nll/topic/conditional-control-flow-across-functions-and-iterators/near/128619294" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122657-t-compiler/wg-nll/topic/conditional-control-flow-across-functions-and-iterators.html#128619294">(Jun 25 2018 at 19:51)</a>:</h4>
<blockquote>
<p>it's just not enabled by default</p>
</blockquote>
<p>Dangerously close to "if a tree falls in the forest" territory here. <span class="emoji emoji-1f609" title="wink">:wink:</span></p>



<a name="128619497"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122657-t-compiler/wg-nll/topic/conditional-control-flow-across-functions-and-iterators/near/128619497" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122657-t-compiler/wg-nll/topic/conditional-control-flow-across-functions-and-iterators.html#128619497">(Jun 25 2018 at 19:56)</a>:</h4>
<p>Ok, It was only stabilized in 1.26, so that's not too long for me to have been missing out</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>